// background.js - 后台服务，管理解锁状态

chrome.runtime.onMessage.addListener((message, sender, sendResponse) => {
  if (message.type === 'unlock') {
    // 处理解锁请求
    const unlockTime = Date.now();
    chrome.storage.local.set({
      unlockCode: message.code,
      unlockTime: unlockTime,
      isUnlocked: true
    }, () => {
      sendResponse({ success: true });
    });
    return true; // 异步响应
  }

  if (message.type === 'checkUnlock') {
    // 检查解锁状态
    chrome.storage.local.get(['unlockCode', 'unlockTime', 'isUnlocked'], (result) => {
      if (result.isUnlocked && result.unlockTime) {
        const elapsed = Date.now() - result.unlockTime;
        const remaining = 12 * 60 * 60 * 1000 - elapsed;
        
        if (remaining > 0) {
          sendResponse({ 
            isUnlocked: true, 
            remaining: remaining,
            code: result.unlockCode 
          });
        } else {
          // 已过期，清除
          chrome.storage.local.remove(['unlockCode', 'unlockTime', 'isUnlocked']);
          sendResponse({ isUnlocked: false });
        }
      } else {
        sendResponse({ isUnlocked: false });
      }
    });
    return true; // 异步响应
  }

  if (message.type === 'searchTracks') {
    doSearch(message.keyword, message.page || 1, message.size || 30)
      .then((data) => sendResponse({ ok: true, items: data }))
      .catch(() => sendResponse({ ok: false }));
    return true;
  }

  if (message.type === 'resolveStream') {
    resolveStream(message.detailUrl, message.id, message.platform)
      .then((res) => {
        if (typeof res === 'string') {
          sendResponse({ ok: !!res, url: res });
        } else {
          sendResponse({ ok: !!res.url, url: res.url || '', error: res.needUnlock ? 'needUnlock' : undefined });
        }
      })
      .catch(() => sendResponse({ ok: false }));
    return true;
  }
});

// 监听标签页更新，如果是 flac.life 且已解锁，自动输入解锁码
chrome.tabs.onUpdated.addListener((tabId, changeInfo, tab) => {
  if (changeInfo.status === 'complete' && tab.url && tab.url.includes('flac.life')) {
    chrome.storage.local.get(['unlockCode', 'unlockTime', 'isUnlocked'], (result) => {
      if (result.isUnlocked && result.unlockTime) {
        const elapsed = Date.now() - result.unlockTime;
        const remaining = 12 * 60 * 60 * 1000 - elapsed;
        
        if (remaining > 0) {
          // 发送消息给 content script
          chrome.tabs.sendMessage(tabId, {
            type: 'autoUnlock',
            code: result.unlockCode
          }).catch(() => {
            // 忽略错误（可能是 content script 未加载）
          });
        }
      }
    });
  }
});

async function doSearch(keyword, page = 1, size = 30) {
  const q = encodeURIComponent(keyword || '');
  const p = Number(page) > 0 ? Number(page) : 1;
  const s = Number(size) > 0 ? Number(size) : 30;
  const api = `https://api.flac.life/search/kuwo?keyword=${q}&page=${p}&size=${s}`;
  try {
    const res = await fetch(api, { credentials: 'omit', cache: 'no-store' });
    const data = await res.json();
    if (!data || data.success !== true || !data.result || !Array.isArray(data.result.list)) return [];
    const items = data.result.list.map((x) => ({
      id: x.id,
      title: x.name,
      artist: Array.isArray(x.singers) ? x.singers.join('/') : '',
      album: x.albumName || '',
      duration: '',
      cover: x.picUrl || '',
      detailUrl: '',
      url: '',
      platform: x.platform || 'kuwo'
    }));
    // 按用户要求：仅返回搜索列表，不预先请求播放接口
    return items;
  } catch (_) {
    return [];
  }
}

// 不再在搜索阶段并发解析播放地址，按需点击时再解析

function parseSearchHtml(html) {
  const results = [];
  const seen = new Set();

  // 优先：按 WordPress 文章结构解析 <article> 块
  const articleRegex = /<article[\s\S]*?<\/article>/gi;
  let a;
  while ((a = articleRegex.exec(html))) {
    const block = a[0];
    const linkMatch = /<a[^>]+href=["']([^"']+)["'][^>]*>([\s\S]*?)<\/a>/i.exec(block);
    if (!linkMatch) continue;
    const href = linkMatch[1];
    let title = linkMatch[2] || '';
    title = title.replace(/<[^>]+>/g, ' ').replace(/\s+/g, ' ').trim();
    if (!href || !title || seen.has(href)) continue;
    const cover = extractFirstImage(block) || extractFirstImage(html);
    seen.add(href);
    results.push({ id: href, title, artist: '', album: '', duration: '', cover, detailUrl: absolutize(href) });
    if (results.length >= 50) break;
  }

  if (results.length) return results;

  // 退化策略：抓取页面上可能是“搜索结果标题”的链接（h2/h3 内 a）
  const hLinkRegex = /<(h2|h3)[^>]*>\s*<a[^>]+href=["']([^"']+)["'][^>]*>([\s\S]*?)<\/a>\s*<\/\1>/gi;
  let h;
  while ((h = hLinkRegex.exec(html))) {
    const href = h[2];
    let title = h[3] || '';
    title = title.replace(/<[^>]+>/g, ' ').replace(/\s+/g, ' ').trim();
    if (!href || !title || seen.has(href)) continue;
    seen.add(href);
    results.push({ id: href, title, artist: '', album: '', duration: '', cover: extractFirstImage(html), detailUrl: absolutize(href) });
    if (results.length >= 50) break;
  }

  if (results.length) return results;

  // 最后：从页面所有链接中筛掉静态资源，保留看起来是文章的链接
  const aRegex = /<a[^>]+href=["']([^"']+)["'][^>]*>([\s\S]*?)<\/a>/gi;
  let m;
  while ((m = aRegex.exec(html))) {
    const href = m[1];
    let text = (m[2] || '').replace(/<[^>]+>/g, ' ').replace(/\s+/g, ' ').trim();
    if (!href || seen.has(href)) continue;
    if (href.includes('wp-') || href.match(/\.(?:css|js|png|jpg|jpeg|gif|svg|webp)(?:\?|$)/i)) continue;
    if (href.includes('/category/') || href.includes('/tag/')) continue;
    if (!text || text.length < 2) continue;
    seen.add(href);
    results.push({ id: href, title: text.slice(0, 120), artist: '', album: '', duration: '', cover: extractFirstImage(html), detailUrl: absolutize(href) });
    if (results.length >= 30) break;
  }

  return results;
}

function extractFirstImage(block) {
  const imgMatch = /<img[^>]+src=["']([^"']+)["'][^>]*>/i.exec(block || '');
  return imgMatch ? absolutize(imgMatch[1]) : '';
}

function absolutize(url) {
  try {
    if (!url) return '';
    if (url.startsWith('http')) return url;
    if (url.startsWith('//')) return 'https:' + url;
    if (url.startsWith('/')) return 'https://flac.life' + url;
    return 'https://flac.life/' + url.replace(/^\.?\//, '');
  } catch (_) {
    return url;
  }
}

async function resolveStream(detailUrl, id, platform) {
  // 使用你提供的播放接口规范：/url/{platform}/{id}/128
  const trackId = id || detailUrl || '';
  const pf = platform || 'kuwo';
  if (!trackId) return '';
  const api = `https://api.flac.life/url/${encodeURIComponent(pf)}/${encodeURIComponent(trackId)}/128`;
  try {
    const unlock = await getUnlockInfo();
    const headers = buildUnlockHeaders(unlock);
    // 首次尝试：带上解锁头，且包含凭证（Cookie）
    let r = await fetch(api, { credentials: 'include', cache: 'no-store', headers });
    let j = await r.json().catch(() => null);
    // 若接口明确返回未解锁或 code 为 500（解锁问题）
    if (j && (j.code === 500 || (j.success === false && /解锁/.test(String(j.message || ''))))) {
      chrome.storage.local.remove(['unlockCode', 'unlockTime', 'isUnlocked']);
      return { url: '', needUnlock: true };
    }
    let url = j && (j.result || j.message);
    if (url) return { url };
    // 若仍被拒绝，尝试在查询参数加入 token 兜底
    if (unlock && unlock.code) {
      const urlWithToken = api + `?token=${encodeURIComponent(sanitizeUnlockCode(unlock.code))}`;
      r = await fetch(urlWithToken, { credentials: 'include', cache: 'no-store', headers });
      j = await r.json().catch(() => null);
      if (j && (j.code === 500 || (j.success === false && /解锁/.test(String(j.message || ''))))) {
        chrome.storage.local.remove(['unlockCode', 'unlockTime', 'isUnlocked']);
        return { url: '', needUnlock: true };
      }
      url = j && (j.result || j.message);
      if (url) return { url };
    }
  } catch (_) {}
  // 兜底：若传入的是网页，尝试 HTML 提取（不推荐，低优先级）
  if (detailUrl && /^https?:\/\//.test(detailUrl)) {
    try {
      const res = await fetch(detailUrl, { credentials: 'omit', cache: 'no-store' });
      const html = await res.text();
      const link = findAudioUrl(html) || findAudioUrlFromScript(html);
      if (link) return { url: link };
    } catch (_) {}
  }
  return { url: '' };
}

function buildUnlockHeaders(unlock) {
  const headers = {};
  if (!unlock || !unlock.isUnlocked || !unlock.valid || !unlock.code) return headers;
  const code = sanitizeUnlockCode(unlock.code);
  if (!code) return headers;
  headers['unlockcode'] = code;
  return headers;
}

async function getUnlockInfo() {
  return new Promise((resolve) => {
    chrome.storage.local.get(['unlockCode', 'unlockTime', 'isUnlocked'], (r) => {
      const code = sanitizeUnlockCode(r.unlockCode);
      const isUnlocked = !!r.isUnlocked;
      const unlockTime = r.unlockTime || 0;
      const elapsed = Date.now() - unlockTime;
      const valid = isUnlocked && unlockTime && (elapsed < 12 * 60 * 60 * 1000);
      resolve({ code, isUnlocked, valid });
    });
  });
}

function sanitizeUnlockCode(raw) {
  if (!raw) return '';
  const first = String(raw).split(/[\s,;]+/).filter(Boolean)[0] || '';
  return first.trim();
}

function findAudioUrl(html) {
  const audioRegex = /(https?:[^\s"'<>]+\.(?:flac|mp3|m4a))(?:\?[\w=&%-]+)?/i;
  const m = audioRegex.exec(html);
  return m ? m[1] : '';
}

function findAudioUrlFromScript(html) {
  // 有些页面会在脚本里放音频地址
  const scriptRegex = /(?:src|url)\s*[:=]\s*["'](https?:[^"']+\.(?:flac|mp3|m4a)[^"']*)["']/i;
  const m = scriptRegex.exec(html);
  return m ? m[1] : '';
}

